package vista;

import clases.Articulo;
import clases.Categoria;
import com.alee.extended.image.WebDecoratedImage;
import com.alee.extended.image.WebImage;
import com.alee.extended.panel.GroupPanel;
import com.alee.laf.button.WebButton;
import com.alee.laf.combobox.WebComboBox;
import com.alee.laf.label.WebLabel;
import com.alee.laf.optionpane.WebOptionPane;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.rootpane.WebDialog;
import com.alee.laf.rootpane.WebFrame;
import com.alee.laf.spinner.WebSpinner;
import com.alee.laf.text.WebTextField;
import controlador.CtrlArticulo;
import controlador.CtrlCategoria;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.SpinnerNumberModel;
import javax.swing.SpringLayout;

/**
 * Formulario para crear, editar y/o eliminar un artículo
 * @author Edder
 * @version 1.0
 */
public class FrmArticulo extends WebDialog implements ActionListener{
    private CtrlArticulo ctrlArticulo;
    private CtrlCategoria ctrlCategoria;
    private Articulo articulo;
    private ArrayList<Categoria> categorias;
    
    private WebPanel container;
    private WebTextField 
            txtNombre,
            txtPresentacion,
            txtDescripcion,
            txtTamaño,
            txtUnidad,
            txtPrecio,
            txtBarCode;
    private WebComboBox cboCategoria;
    private WebSpinner txtStockMinimo;    
    private WebDecoratedImage imgArticulo;
    private WebButton btnChangeImage, btnGenerateBarCode, btnEliminar, btnGuardar, btnCancelar;
    private WebLabel lblId;
    
    /**
     * Constructor principal, sin parámetros para crear nuevo artículo
     */
    FrmArticulo(WebFrame owner, boolean modal){
        super(owner, modal);
        setTitle("Articulos");
        setSize(600, 400);
        setDefaultCloseOperation(WebDialog.DISPOSE_ON_CLOSE);
        setShowResizeCorner(false);
        setShowMaximizeButton(false);
        initComponents();
        this.setLocationRelativeTo(null);
    }
    
    /**
     * Carga la información de un artículo, para editar o eliminar
     * @param articulo 
     */
    FrmArticulo(WebFrame owner, boolean modal, Articulo articulo){
        this(owner, modal);
        setArticulo(articulo);
    }

    /**
     * Buscar el artículo en la base de datos y carga la información para editar o eliminar
     * Si no encuentra el artículo muestra mensaje y el formulario aparece vacío para crear nuevo artículo
     * @param idArticulo 
     */
    FrmArticulo(WebFrame owner, boolean modal, int idArticulo){
        this(owner, modal);
        setArticulo(idArticulo);
    }
    
    /**
     * Carga la información de un artículo, para editar o eliminar
     * @param articulo 
     */
    private void setArticulo(Articulo articulo) {        
        this.articulo = articulo;
        llenarDatos();
    }
    
    /**
     * Buscar el artículo en la base de datos y carga la información para editar o eliminar
     * Si no encuentra el artículo muestra mensaje y el formulario aparece vacío para crear nuevo artículo
     * @param idArticulo 
     */
    private void setArticulo(int idArticulo){
        try {
            this.articulo = this.ctrlArticulo.get(idArticulo, null);
        } catch (ClassNotFoundException | SQLException ex) {
            this.articulo = null;            
        } finally{
            if(this.articulo == null)
                WebOptionPane.showMessageDialog(
                        this,
                        "No se pudo cargar el artículo",
                        "Error", 
                        WebOptionPane.ERROR_MESSAGE);
            llenarDatos();
        }
    }
    
    /**
     * Carga la información del artículo, si es null, deja los campos vacíos
     */
    private void llenarDatos(){
        if(this.articulo != null){
            this.txtNombre.setText(this.articulo.getNombre());
            this.txtPresentacion.setText(this.articulo.getPresentacion());
            this.txtDescripcion.setText(this.articulo.getDescripcion());
            this.cboCategoria.setSelectedItem(getCategoria());
            this.txtTamaño.setText(String.valueOf(this.articulo.getTamaño()));
            this.txtUnidad.setText(this.articulo.getUnidad());
            this.txtPrecio.setText(String.valueOf(this.articulo.getPrecioVenta()));
            this.txtStockMinimo.setValue(this.articulo.getStockMinimo());
            String estado = this.articulo.getEstado() == 'A' ? "Activo": "Inactivo";
            this.lblId.setText("ID: " + this.articulo.getIdArticulo() + " - " + estado);            
        }
    }
    
    /**
     * Obtiene el objeto categoría de la lista de categorías, según el idCategoría que hay el this.artículo
     * @return Categoria Según articulo.getCategoria().getidCategoria()
     */
    private Categoria getCategoria(){
        for(Categoria categoria : this.categorias){
            if(this.articulo.getCategoria().getIdCategoria() == categoria.getIdCategoria())
                return categoria;
        }
        return null;
    }
    
    /**
     *  Guarda la información, si es nuevo inserta, sino actualiza
     */
    private void guardar(){
        if(this.articulo == null){
            this.articulo = new Articulo();
            this.articulo.setIdArticulo(-1);
            this.articulo.setEstado('A');
        }
        prepararDatos();
        if(this.articulo.getIdArticulo() == -1){
            try {
                //Crear
                this.ctrlArticulo.insert(this.articulo, null);
                this.lblId.setText("ID: " + String.valueOf(this.articulo.getIdArticulo()));
                WebOptionPane.showMessageDialog(
                        this,
                        "Información registrada correctamente",
                        "Éxito",
                        WebOptionPane.INFORMATION_MESSAGE);
                this.dispose();
            } catch (ClassNotFoundException | SQLException ex) {
                WebOptionPane.showMessageDialog(
                        this,
                        "No se pudo guardar la información, verificar e intentar nuevamente",
                        "Error",
                        WebOptionPane.ERROR_MESSAGE);
            }
        }else{
            try {
                this.ctrlArticulo.update(this.articulo, null);
                WebOptionPane.showMessageDialog(
                        this,
                        "Información registrada correctamente",
                        "Éxito",
                        WebOptionPane.INFORMATION_MESSAGE);
                this.dispose();
            } catch (ClassNotFoundException | SQLException ex) {
                WebOptionPane.showMessageDialog(
                        this,
                        "No se pudo guardar la información, verificar e intentar nuevamente",
                        "Error",
                        WebOptionPane.ERROR_MESSAGE);
            }
        }
    }
    
    /**
     * Da de baja el artículo, cambia de estado
     */
    private void eliminar(){
        if(WebOptionPane.showConfirmDialog(
                this,
                "¿Seguro que desea eliminar el artículo?",
                "Advertencia",
                WebOptionPane.YES_NO_OPTION,
                WebOptionPane.WARNING_MESSAGE) == WebOptionPane.YES_OPTION)
            try {
                this.ctrlArticulo.dar_baja(this.articulo, null);
                WebOptionPane.showMessageDialog(
                        this,
                        "Artículo eliminado",
                        "Éxito",
                        WebOptionPane.INFORMATION_MESSAGE);
                this.dispose();
            } catch (ClassNotFoundException | SQLException ex) {
                WebOptionPane.showMessageDialog(
                        this,
                        "No se pudo eliminar el artículo, verificar e intentar nuevamente",
                        "Error",
                        WebOptionPane.ERROR_MESSAGE);
            }
    }
    
    /**
     * Asigna la información de los campos del formulario al objeto categoría
     */
    private void prepararDatos(){
        this.articulo.setNombre(this.txtNombre.getText());
        this.articulo.setPresentacion(this.txtPresentacion.getText());
        this.articulo.setDescripcion(this.txtDescripcion.getText());
        this.articulo.setStockMinimo((Integer)this.txtStockMinimo.getValue());
        this.articulo.setTamaño(this.txtTamaño.getText());
        this.articulo.setUnidad(this.txtUnidad.getText());
        this.articulo.setCodigoBarras(this.txtBarCode.getText());
        this.articulo.setCategoria((Categoria)this.cboCategoria.getSelectedItem());
        this.articulo.setPrecioVenta(Float.parseFloat(this.txtPrecio.getText()));
        this.articulo.setUrlImagen("");
    }
    
    /**
     * Inicializa los componentes del formulario
     */
    private void initComponents(){
        try {
            this.setIconImage(new ImageIcon(getClass().getResource("/resources/img/cart_add.png")).getImage());
            this.container = new WebPanel();
            this.container.setBackground(Color.white);
            this.ctrlArticulo = new CtrlArticulo();
            this.ctrlCategoria = new CtrlCategoria();
            
            this.txtNombre = new WebTextField(20);
            this.txtPresentacion = new WebTextField(10);
            this.txtDescripcion = new WebTextField(10);
            this.txtTamaño = new WebTextField();
            this.txtUnidad = new WebTextField();
            this.txtPrecio = new WebTextField();
            this.txtPrecio.setTrailingComponent(new WebImage(getClass().getResource("/resources/img/coins.png")));
            
            this.categorias = this.ctrlCategoria.getCategorias("", null);
            this.cboCategoria = new WebComboBox(this.categorias.toArray());
            this.txtStockMinimo = new WebSpinner();
            SpinnerNumberModel snm = new SpinnerNumberModel();
            this.txtStockMinimo.setModel(snm);
            this.btnChangeImage = new WebButton("Cambiar imagen");
            this.txtBarCode = new WebTextField(10);
            this.btnGenerateBarCode = new WebButton("Generar código");
            
            this.btnEliminar = new WebButton("Eliminar", new ImageIcon(getClass().getResource("/resources/img/delete.png")));
            this.btnGuardar = new WebButton("Guardar", new ImageIcon(getClass().getResource("/resources/img/disk.png")));
            this.btnCancelar = new WebButton("Cancelar", new ImageIcon(getClass().getResource("/resources/img/cancel.png")));
            
            this.lblId = new WebLabel("ID: ");
            
            ImageIcon img = new ImageIcon(getClass().getResource("/resources/img/imgarticle.png"));

            this.add(this.container);
            this.container.setLayout(new BorderLayout());
            
            this.container.add(new GroupPanel(){
                {
                    this.setLayout(new BorderLayout());
                    this.add(new GroupPanel(){
                        {
                            this.setLayout(new BorderLayout());
                            this.add(new GroupPanel(){
                                {
                                    this.setLayout(new BorderLayout());
                                    imgArticulo = new WebDecoratedImage(img.getImage().getScaledInstance(150, 150, Image.SCALE_DEFAULT));
                                    this.add(imgArticulo, BorderLayout.CENTER);
                                    this.add(btnChangeImage, BorderLayout.SOUTH);                                    
                                }
                            }, BorderLayout.CENTER);
                            this.add(new GroupPanel(){
                                {
                                    setLayout(new SpringLayout());
                                    WebLabel lblBarCode = new WebLabel("Barras");
                                    lblBarCode.setLabelFor(txtBarCode);
                                    this.add(lblBarCode);
                                    this.add(txtBarCode);
                                    this.add(new WebLabel());
                                    this.add(btnGenerateBarCode);
                                    
                                    SpringUtilities.makeCompactGrid(this,
                                            2, 2,
                                            6, 6,
                                            6, 6);
                                }
                            }, BorderLayout.SOUTH);
                        }
                    }, BorderLayout.WEST);
                    this.add(new GroupPanel(){
                        {
                            setLayout(new SpringLayout());
                            WebLabel lblNombre = new WebLabel("Nombre");
                            lblNombre.setLabelFor(txtNombre);
                            this.add(lblNombre);
                            this.add(txtNombre);
                            
                            WebLabel lblPresentacion = new WebLabel("Presentacion");
                            lblPresentacion.setLabelFor(txtPresentacion);
                            this.add(lblPresentacion);
                            this.add(txtPresentacion);
                            
                            WebLabel lblDescripcion = new WebLabel("Descripcion");
                            lblDescripcion.setLabelFor(txtDescripcion);
                            this.add(lblDescripcion);
                            this.add(txtDescripcion);

                            WebLabel lblCategoria = new WebLabel("Categoria");
                            lblCategoria.setLabelFor(cboCategoria);
                            this.add(lblCategoria);
                            this.add(cboCategoria);

                            WebLabel lblTamaño = new WebLabel("Tamaño");
                            lblTamaño.setLabelFor(txtTamaño);
                            this.add(lblTamaño);
                            this.add(txtTamaño);

                            WebLabel lblUnidad = new WebLabel("Unidad");
                            lblUnidad.setLabelFor(txtUnidad);
                            this.add(lblUnidad);
                            this.add(txtUnidad);

                            WebLabel lblPrecio = new WebLabel("Precio");
                            lblPrecio.setLabelFor(txtPrecio);
                            this.add(lblPrecio);
                            this.add(txtPrecio);

                            WebLabel lblStockMinimo = new WebLabel("Stock Mínimo");
                            lblStockMinimo.setLabelFor(txtStockMinimo);
                            this.add(lblStockMinimo);
                            this.add(txtStockMinimo);

                            SpringUtilities.makeCompactGrid(this,
                                        8, 2,
                                        6, 6,
                                        6, 6);
                        }
                    }, BorderLayout.CENTER);
                }
            },BorderLayout.CENTER); 
            
            this.container.add(new GroupPanel(){
                {
                    this.setLayout(new BorderLayout());
                    this.add(lblId, BorderLayout.WEST);
                    this.add(new GroupPanel(){
                        {
                            this.setLayout(new FlowLayout(FlowLayout.RIGHT));
                            this.add(btnEliminar, btnGuardar, btnCancelar);
                        }
                    }, BorderLayout.EAST);
                }
            }, BorderLayout.SOUTH);
            this.btnEliminar.addActionListener(this);
            this.btnGuardar.addActionListener(this);
            this.btnCancelar.addActionListener(this);
            this.addWindowListener(new WindowListener() {

                @Override
                public void windowOpened(WindowEvent e) {
                    txtNombre.requestFocusInWindow();
                }

                @Override
                public void windowClosing(WindowEvent e) {}

                @Override
                public void windowClosed(WindowEvent e) {}

                @Override
                public void windowIconified(WindowEvent e) {}

                @Override
                public void windowDeiconified(WindowEvent e) {}

                @Override
                public void windowActivated(WindowEvent e) {}

                @Override
                public void windowDeactivated(WindowEvent e) {}
            });
            
            this.pack();
        } catch (ClassNotFoundException | SQLException ex) {
            Logger.getLogger(FrmArticulo.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == this.btnGuardar)
            this.guardar();
        else if(e.getSource() == this.btnCancelar){
            if(WebOptionPane.showConfirmDialog(
                    this,
                    "¿Está seguro que desea cerrar?",
                    "Advertencia",
                    WebOptionPane.YES_NO_OPTION,
                    WebOptionPane.WARNING_MESSAGE) == WebOptionPane.YES_OPTION)
                this.dispose();
        }
        else if(e.getSource() == this.btnEliminar)
            this.eliminar();
        /**
         * Un posible cambio es que el botón Eliminar sea eliminar cuando el artículo está activo, activa cuando está inactivo
         * y que se oculte cuando se está agregando un artículo
         */
    }
}